package com.secret.chain.secretchain.solidity;

import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple5;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@SuppressWarnings("unchecked")
public class Collect extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b5061024d806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a2e620451161005b578063a2e62045146100f8578063eccd65dc14610116578063efc81a8c1461016c578063fe587bc71461018a5761007d565b8063200d2ed21461008257806358975919146100a05780636d4ce63c146100be575b600080fd5b61008a6101a8565b6040518082815260200191505060405180910390f35b6100a86101ae565b6040518082815260200191505060405180910390f35b6100c66101b4565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6101006101db565b6040518082815260200191505060405180910390f35b61016a600480360360a081101561012c57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291905050506101e1565b005b61017461020b565b6040518082815260200191505060405180910390f35b610192610211565b6040518082815260200191505060405180910390f35b60045481565b60005481565b60008060008060008054600154600254600354600454945094509450945094509091929394565b60035481565b84600081905550836001819055508260028190555081600381905550806004819055505050505050565b60025481565b6001548156fea26469706673582212205637999b7e5dd013a69eb71eda20e67afab2dbb09dc5e11caf1625220bc25eb664736f6c634300060a0033"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {"608060405234801561001057600080fd5b5061024d806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a2e620451161005b578063a2e62045146100f8578063eccd65dc14610116578063efc81a8c1461016c578063fe587bc71461018a5761007d565b8063200d2ed21461008257806358975919146100a05780636d4ce63c146100be575b600080fd5b61008a6101a8565b6040518082815260200191505060405180910390f35b6100a86101ae565b6040518082815260200191505060405180910390f35b6100c66101b4565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6101006101db565b6040518082815260200191505060405180910390f35b61016a600480360360a081101561012c57600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291905050506101e1565b005b61017461020b565b6040518082815260200191505060405180910390f35b610192610211565b6040518082815260200191505060405180910390f35b60045481565b60005481565b60008060008060008054600154600254600354600454945094509450945094509091929394565b60035481565b84600081905550836001819055508260028190555081600381905550806004819055505050505050565b60025481565b6001548156fea26469706673582212205637999b7e5dd013a69eb71eda20e67afab2dbb09dc5e11caf1625220bc25eb664736f6c634300060a0033"};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"name\":\"articleId\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"articleId()\"},{\"name\":\"create\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"create()\"},{\"name\":\"get\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"get()\"},{\"name\":\"set\",\"type\":\"function\",\"constant\":false,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"nonpayable\",\"inputs\":[{\"name\":\"_userId\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_articleId\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_create\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_update\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_status\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"outputs\":[],\"methodSignatureAsString\":\"set(uint256,uint256,uint256,uint256,uint256)\"},{\"name\":\"status\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"status()\"},{\"name\":\"update\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"update()\"},{\"name\":\"userId\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"userId()\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_ARTICLEID = "articleId";

    public static final String FUNC_CREATE = "create";

    public static final String FUNC_GET = "get";

    public static final String FUNC_SET = "set";

    public static final String FUNC_STATUS = "status";

    public static final String FUNC_UPDATE = "update";

    public static final String FUNC_USERID = "userId";

    protected Collect(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public BigInteger articleId() throws ContractException {
        final Function function = new Function(FUNC_ARTICLEID, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public BigInteger create() throws ContractException {
        final Function function = new Function(FUNC_CREATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public Tuple5<BigInteger, BigInteger, BigInteger, BigInteger, BigInteger> get() throws ContractException {
        final Function function = new Function(FUNC_GET, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = executeCallWithMultipleValueReturn(function);
        return new Tuple5<BigInteger, BigInteger, BigInteger, BigInteger, BigInteger>(
                (BigInteger) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue(), 
                (BigInteger) results.get(3).getValue(), 
                (BigInteger) results.get(4).getValue());
    }

    public TransactionReceipt set(BigInteger _userId, BigInteger _articleId, BigInteger _create, BigInteger _update, BigInteger _status) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_userId),
                new Uint256(_articleId),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void set(BigInteger _userId, BigInteger _articleId, BigInteger _create, BigInteger _update, BigInteger _status, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_userId),
                new Uint256(_articleId),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSet(BigInteger _userId, BigInteger _articleId, BigInteger _create, BigInteger _update, BigInteger _status) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_userId),
                new Uint256(_articleId),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple5<BigInteger, BigInteger, BigInteger, BigInteger, BigInteger> getSetInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_SET, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple5<BigInteger, BigInteger, BigInteger, BigInteger, BigInteger>(

                (BigInteger) results.get(0).getValue(), 
                (BigInteger) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue(), 
                (BigInteger) results.get(3).getValue(), 
                (BigInteger) results.get(4).getValue()
                );
    }

    public BigInteger status() throws ContractException {
        final Function function = new Function(FUNC_STATUS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public BigInteger update() throws ContractException {
        final Function function = new Function(FUNC_UPDATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public BigInteger userId() throws ContractException {
        final Function function = new Function(FUNC_USERID, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public static Collect load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new Collect(contractAddress, client, credential);
    }

    public static Collect deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(Collect.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }
}
